package com.hanshg.cherry.controller.oauth;

import com.hanshg.cherry.dto.LoginUser;
import com.hanshg.cherry.mapper.PermissionMapper;
import com.hanshg.cherry.model.SysPermission;
import com.hanshg.cherry.model.SysUser;
import com.hanshg.cherry.service.oauth.OAuthService;
import com.hanshg.cherry.util.oauth.StateUtils;
import com.xkcoding.justauth.AuthRequestFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

/**
 * 第三方登录 Controller
 *
 * @Author hanshg
 * @Description //TODO
 * @Date 2021/8/15
 * @Param
 * @return
 **/
@Controller
@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class OAuthController {

    private final AuthRequestFactory factory;

    private final OAuthService OAuthService;

    private final PermissionMapper permissionMapper;

    @GetMapping("/authLogin/{type}")
    public void renderAuth(@PathVariable String type, HttpServletResponse response) throws IOException {
        log.info("第三方登录启动");
        AuthRequest authRequest = factory.get(type);
        response.sendRedirect(authRequest.authorize(StateUtils.createState()));
    }

    @RequestMapping(value = {"/callbackqq", "/callbackgitee", "/callbackwechat_open",
            "/callbackdingtalk", "/callbackbaidu", "/callbackalipay", "/callbackweibo",
            "/callbackdouyin", "/callbackjd", "/callbackjd", "/callbackoschina",
            "/callbackcoding", "callbackhuawei", "/callbackgithub", "callbackaliyun"})
    public ModelAndView callback(AuthCallback callback, HttpServletRequest request) {
        // 验证state为了用于防止跨站请求伪造攻击
        if (StateUtils.checkState(callback.getState())) {
            ModelAndView model = new ModelAndView("forward:/login.html");
            return model;
        }
        //获取type
        String uri = request.getRequestURI();
        String type = StringUtils.substringAfter(uri, "callback");
        if (StringUtils.isEmpty(uri)) {
            throw new UsernameNotFoundException("很抱歉，第三方登录类型错误");
        }
        AuthRequest authRequest = factory.get(type);
        AuthResponse<AuthUser> response = authRequest.login(callback);
        if (response.ok()) {
            LoginUser loginUser = new LoginUser();
            SysUser sysUser = OAuthService.login(response.getData());
            log.info("登录成功：" + sysUser);
            BeanUtils.copyProperties(sysUser, loginUser);

            //获取权限
            List<SysPermission> permissions = permissionMapper.listByUserId(loginUser.getId());
            loginUser.setPermissions(permissions);
            log.info("权限赋值完成");

            // 登录系统
            log.info("系统认证启动");
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginUser, loginUser.getPassword(), loginUser.getAuthorities());
            authentication.setDetails(loginUser);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            log.info("系统认证通过");

            HttpSession session = request.getSession();
            session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
            Authentication authenticated = SecurityContextHolder.getContext().getAuthentication();
            log.info("认证通过信息：" + authenticated);

            //存储信息返回页面
            ModelAndView model = new ModelAndView("forward:/");
            model.addObject("authentication", authenticated);
            return model;
        } else {
            throw new UsernameNotFoundException("很抱歉，登录异常，原因是： " + response.getMsg());
        }

    }
}